/*******************************************************************************************
 * File:   board_init.c
 * Description: 主板初始化
 *
 *  SWD+UART1; 短扩展口EXP2:PA2/PA3->UART2; TYPEC左USB-COM：UART3;
 *  TYPEC右USB-DEBUG ;蓝牙PC10/11:UART4;长扩展口EXP1: PD2/PC12:UART5
 *
 * freeRtos  独立线程运行  先 Board_Init()  后 Motor_Init()
 * 1. BuzzerBeep()  蜂鸣器鸣叫
 * 2. LedGreen_Blink(3)  LED3闪烁3次
 * 3. 重定向printf到UART,方便调试; 开启printf()浮点数支持
 * 4.
 * 5. 启动HAL_ADC_Start(&hadc1); 启动ADC 获取电压使能
 * 6. OLED 使能
 * 7. UART5 连接遥控器,开启DMA中断读取遥控器数据（dma callback 接收中断回调）
 *********************************************************************************************/

#include "board_init.h"

asm(".global _printf_float"); // 使能printf浮点数支持

uint8_t uart5_rx_buffer[32] = {0};
SBUS_Parser sbus_parser; /// 声明一个sbus解析器对象

// 开机初始化
void Board_Init()
{
    BuzzerBeep(3);
    LedRedBlink(2);
    LedGreenBlink(2);
    HAL_ADC_Start(&hadc1); // 开启ADC用于电压读取

    AX_OLED_Init(); // OLED初始化
    AX_OLED_ClearScreen();

    HAL_UARTEx_ReceiveToIdle_DMA(&huart5, uart5_rx_buffer, sizeof(uart5_rx_buffer)); // 启动DMA接收,用来接收遥控器数据
    __HAL_DMA_DISABLE_IT(huart5.hdmarx, DMA_IT_HT);                                  // 关闭DMA接收缓冲区半满中断
    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_2);
    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_3);
    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_4);
    HAL_TIM_PWM_Start_IT(&htim9, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start_IT(&htim9, TIM_CHANNEL_2);
    HAL_TIM_PWM_Start_IT(&htim12, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start_IT(&htim12, TIM_CHANNEL_2);

    // 电机编码器读取初始化
    HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_1); // 电机A
    HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_1); // 电机B
    HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_1); // 电机C
    HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_1); // 电机D

    // 初始化CAN驱动 传入CAN句柄
    if (BSP_CAN_Init(&hcan1) == 0) {
        printf("CAN初始化成功\r\n");
    }
}
void LedRedBlink(uint8_t times)
{
    for (uint8_t i = 0; i < times; i++)
    {
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); // LED3 低电平有效
        osDelay(200);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_SET); // LED3 低电平有效
    }
}

void LedGreenBlink(uint8_t times)
{
    for (uint8_t i = 0; i < times; i++)
    {
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET); // LED4 低电平有效
        osDelay(200);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET); // LED3 低电平有效
    }
}

void BuzzerBeep(uint8_t times)
{
    for (uint8_t i = 0; i < times; i++)
    {
        HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET); // SPEAKER 高电平有效
        osDelay(250);
        HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET); // SPEAKER close
    }
}

float ADC_ToVoltage(uint16_t adc_value)
{
    // STM32F1 ADC为12位，最大值为4095
    // 参考电压一般为3.3V
    const float VREF = 3.3f;
    return (adc_value * VREF) / 4095.0f;
}

float GetBatteryVoltage()
{
    return ADC_ToVoltage(HAL_ADC_GetValue(&hadc1) * 11 * 0.98); // 10:1分压 补偿0.98
}

//循环读取麦轮速度
void Board_Detect_Loop()
{
    int32_t pr_a = 0;
    int32_t pr_b = 0;
    int32_t pr_c = 0;
    int32_t pr_d = 0;
    uint8_t ch[32] = "hello world!";
    uint16_t pw_volte = 0;
    __HAL_TIM_SET_COUNTER(&htim2, TIM_LOOP_MARK);
    __HAL_TIM_SET_COUNTER(&htim3, TIM_LOOP_MARK);
    __HAL_TIM_SET_COUNTER(&htim5, TIM_LOOP_MARK);
    __HAL_TIM_SET_COUNTER(&htim4, TIM_LOOP_MARK);
    while (1)
    {

        //printf("pw_volte:%5.2f\r\n", GetBatteryVoltage());

        AX_OLED_DispStr(0, 0, ch, 1); // OLED指定位置显示ASCII字符串（6X8）
        AX_OLED_DispValue(0, 16, pw_volte, 2, 2, 0);

        pr_a = __HAL_TIM_GET_COUNTER(&htim2); // 先读取再计算，否则会异常
        pr_b = __HAL_TIM_GET_COUNTER(&htim3);
        pr_c = __HAL_TIM_GET_COUNTER(&htim5);
        pr_d = __HAL_TIM_GET_COUNTER(&htim4);

        pr_a = ((pr_a - TIM_LOOP_MARK) * 60 / 39);      // 390为一圈 0.1秒读一次编码器计数 获取转速/分钟
        pr_b = ((pr_b - TIM_LOOP_MARK) * 60 / 39) * -1; // 390为一圈 0.1秒读一次编码器计数 获取转速/分钟
        pr_c = ((pr_c - TIM_LOOP_MARK) * 60 / 39);      // 390为一圈 0.1秒读一次编码器计数 获取转速/分钟
        pr_d = ((pr_d - TIM_LOOP_MARK) * 60 / 39) * -1; // 390为一圈 0.1秒读一次编码器计数 获取转速/分钟

        __HAL_TIM_SET_COUNTER(&htim2, TIM_LOOP_MARK);
        __HAL_TIM_SET_COUNTER(&htim3, TIM_LOOP_MARK);
        __HAL_TIM_SET_COUNTER(&htim5, TIM_LOOP_MARK);
        __HAL_TIM_SET_COUNTER(&htim4, TIM_LOOP_MARK);
        //printf("Wheel Speed= A:%ld, B=%ld, C=%ld, D=%ld\r\n", pr_a, pr_b, pr_c, pr_d);
        osDelay(100); // 不能改 否则会影响速度计算结果
    }
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    static uint32_t count = 0;
    static uint32_t error = 0;
    char msg[64] = {};

    if (huart->Instance == UART5) // UART5接收中断处理函数
    {

        if (SBUS_Update(&sbus_parser, uart5_rx_buffer, Size))
        {
            count++;
            sprintf(msg, "s:%d, c:%ld, e:%ld", Size, count, error);
            //  AX_OLED_Disp16Str(0,0,msg,0);    //OLED指定位置显示ASCII字符串（8X16）
            // SBUS_PrintChannels(&sbus_parser);    //调试
            HAL_UART_Transmit_IT(&huart1, (uint8_t *)&(sbus_parser.raw_data), Size);
            //   OLED_ShowHexArray(0, 4, (uint8_t *)&(sbus_parser.raw_data), Size);
        }
        else
        {
            error++;

            sprintf(msg, "s:%d, c:%ld, e:%ld", Size, count, error);
            // OLED_ShowString(0, 2, msg);
        }

        HAL_UARTEx_ReceiveToIdle_DMA(&huart5, uart5_rx_buffer, sizeof(uart5_rx_buffer)); // 启动DMA接收
        __HAL_DMA_DISABLE_IT(huart5.hdmarx, DMA_IT_HT);                                  // 关闭DMA接收缓冲区溢出中断
    }
}

// CAN接收中断回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    if (hcan->Instance == CAN1)
    {
        bsp_can_rx_callback();
    }
}

// 重定向printf到UART,方便调试 uart3 左typec uart4 蓝牙
int _write(int file, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, HAL_MAX_DELAY);
    return len;
}